{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 第5篇：文件读取和输出\n",
    "我们拿到的数据一般是 CSV、Excel 等格式，将文件加载到 Pandas 的 DataFrame 对象，我们就可以用它的方法进行处理了。在处理结束后，我们也需要将文件导出 Excel 等格式，方便查看。\n",
    "![](https://www.gairuo.com/file/pic/2020/04/pandas-io-readwrite.svg)\n",
    "\n",
    "数据分析过程中经常需要进行读写操作，Pandas实现了很多 IO 操作的API，这里简单做了一个列举。\n",
    "\n",
    "| 格式类型\t|数据描述\t|读取函数\t|输出（写入）函数|\n",
    "| -- | -- | -- | -- |\n",
    "|text\t|CSV\t|read_ csv\t|to_csv|\n",
    "|text\t|JSON\t|read_json|\tto_json|\n",
    "|ttext\t|HTML\t|read_html|\tto_html|\n",
    "|ttext\t|clipboard\t|read_clipboard\t|to_clipboard|\n",
    "|tbinary\t|Excel\t|read_excel\t|to_excel|\n",
    "|binary\t|HDF5\t|read_hdf\t|to_hdf|\n",
    "|binary\t|Feather\t|read_feather\t|to_feather|\n",
    "|binary\t|Msgpack\t|read_msgpack|\tto_msgpack|\n",
    "|binary\t|Stata\t|read_stata|\tto_stata|\n",
    "|binary\t|SAS\t|read_sas|  |\n",
    "|binary\t|Python Pickle\t|read_pickle\t|to_pickle|\n",
    "|SQL\t|SQL\t|read_sql\t|to_sql|\n",
    "|SQLGoogle\t|Big Query\t|read_gbq\t|to_gbq|\n",
    "\n",
    "\n",
    "本页介绍最常用的文件格式和最基本的用法，如有必要会专题介绍更加详细的功能。\n",
    "读取更多类型文件可查看[官网文档](https://pandas.pydata.org/docs/user_guide/io.html)。\n",
    "\n",
    "其中：\n",
    "- 读取函数一般会赋值给一个变量 df, df = pd.read_<xxx>()\n",
    "- 输出函数是将变量自身进行操作并输出 df.to_<xxx>()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 第1部分：文件读取\n",
    "\n",
    "- 1.read_csv\n",
    "- 2.read_excel\n",
    "- 3.read_html\n",
    "- 4.read_sql\n",
    "- 5.read_sql_table"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### read_csv"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> read_csv(filepath_or_buffer, sep=', ', delimiter=None, header='infer', names=None, index_col=None, usecols=None, squeeze=False, prefix=None, mangle_dupe_cols=True, dtype=None, engine=None, converters=None, true_values=None, false_values=None, skipinitialspace=False, skiprows=None, skipfooter=0, nrows=None, na_values=None, keep_default_na=True, na_filter=True, verbose=False, skip_blank_lines=True, parse_dates=False, infer_datetime_format=False, keep_date_col=False, date_parser=None, dayfirst=False, iterator=False, chunksize=None, compression='infer', thousands=None, decimal=b'.', lineterminator=None, quotechar='\"', quoting=0, doublequote=True, escapechar=None, comment=None, encoding=None, dialect=None, tupleize_cols=None, error_bad_lines=True, warn_bad_lines=True, delim_whitespace=False, low_memory=True, memory_map=False, float_precision=None)\n",
    "\n",
    "- filepath_or_buffer ：可以是URL，可用URL类型包括：http, ftp, s3和文件。对于多文件正在准备中本地文件读取。 \n",
    "- sep：如果不指定参数，则会尝试使用逗号分隔。分隔符长于一个字符并且不是‘\\s+’,将使用python的语法分析器。并且忽略数据中的逗号。正则表达式例子：’\\r\\t’。\n",
    "- delimiter：定界符，备选分隔符（如果指定该参数，则sep参数失效）\n",
    "- delim_whitespace ： 指定空格(例如’ ‘或者’ ‘)是否作为分隔符使用，等效于设定sep=’\\s+’。如果这个参数设定为True那么delimiter 参数失效。\n",
    "- header ：指定行数用来作为列名，数据开始行数。如果文件中没有列名，则默认为0【第一行数据】，否则设置为None。如果明确设定 header = 0 就会替换掉原来存在列名。header参数可以是一个list例如：[0,1,3]，这个list表示将文件中的这些行作为列标题（意味着每一列有多个标题），介于中间的行将被忽略掉。注意：如果skip_blank_lines=True 那么header参数忽略注释行和空行，所以header=0表示第一行数据而不是文件的第一行。\n",
    "- names ：用于结果的列名列表，如果数据文件中没有列标题行，就需要执行 header=None。names属性在header之前运行默认列表中不能出现重复，除非设定参数mangle_dupe_cols=True。\n",
    "- index_col ：用作行索引的列编号或者列名，如果给定一个序列则有多个行索引。\n",
    "- usecols：返回一个数据子集，该列表中的值必须可以对应到文件中的位置（数字可以对应到指定的列）或者是字符传为文件中的列名。例如：usecols有效参数可能是 [0,1,2]或者是 [‘foo’, ‘bar’, ‘baz’]。使用这个参数可以加快加载速度并降低内存消耗。\n",
    "- prefix：在没有列标题时，也就是header设定为None，给列添加前缀。例如：添加prefix= ‘X’ 使得列名称成为 X0, X1, …\n",
    "- dtype： 每列数据的数据类型。例如 {‘a’: np.float64, ‘b’: np.int32}\n",
    "- skipinitialspace：忽略分隔符后的空白（默认为False，即不忽略）.\n",
    "- skiprows ：需要忽略的行数（从文件开始处算起），或需要跳过的行号列表（从0开始）。\n",
    "- nrows ：需要读取的行数（从文件头开始算起）。\n",
    "- na_values ：一组用于替换NA/NaN的值。如果传参，需要制定特定列的空值。默认为‘1.#IND’, ‘1.#QNAN’, ‘N/A’, ‘NA’, ‘NULL’, ‘NaN’, ‘nan’`.\n",
    "- keep_default_na：如果指定na_values参数，并且keep_default_na=False，那么默认的NaN将被覆盖，否则添加\n",
    "- na_filter：是否检查丢失值（空字符串或者是空值）。对于大文件来说数据集中没有空值，设定na_filter=False可以提升读取速度。\n",
    "- skip_blank_lines ：如果为True，则跳过空行；否则记为NaN。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### read_excel\n",
    "\n",
    "> read_excel(io, sheetname=0,header=0,skiprows=None,index_col=None,names=None,\n",
    "                arse_cols=None,date_parser=None,na_values=None,thousands=None,\n",
    "                convert_float=True,has_index_names=None,converters=None,dtype=None,\n",
    "                true_values=None,false_values=None,engine=None,squeeze=False,**kwags)\n",
    "\n",
    "**重要参数详解：**\n",
    "- io ：excel 路径\n",
    "- sheetname：默认是sheetname为0，返回多表使用sheetname=[0,1]，若sheetname=None是返回全表 。注意：int/string返回的是dataframe，而none和list返回的是dict of dataframe。\n",
    "- header ：指定作为列名的行，默认0，即取第一行，数据为列名行以下的数据；若数据不含列名，则设定 header = None；\n",
    "- skiprows：省略指定行数的数据\n",
    "- skip_footer：省略从尾部数的行数据\n",
    "- index_col ：指定列为索引列，也可以使用 u’string’\n",
    "- names：指定列的名字，传入一个list数据\n",
    "                "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### read_html\n",
    "\n",
    "> read_html(io, match='.+', flavor=None, header=None, index_col=None, skiprows=None, attrs=None, parse_dates=False, tupleize_cols=None, thousands=', ', encoding=None, decimal='.', converters=None, na_values=None, keep_default_na=True)\n",
    "\n",
    "**参数详解:**\n",
    "\n",
    "- io : str or file-like, 接收网址、文件、字符串。网址不接受https，尝试去掉s后爬去\n",
    "\n",
    "- match : str or compiled regular expression, optional,正则表达式，返回与正则表达式匹配的表格。\n",
    "\n",
    "- flavor : str or None, container of strings, 解析器默认为‘lxml’\n",
    "\n",
    "- header : int or list-like or None, optional,指定列标题所在的行，list为多重索引\n",
    "\n",
    "- index_col : int or list-like or None, optional,指定行标题对应的列，list为多重索引\n",
    "\n",
    "- skiprows : int or list-like or slice or None, optional,跳过第n行（序列标示）或跳过n行（整数标示）\n",
    "\n",
    "- attrs : dict or None, optional,attrs = {'id': 'table'},attrs = {'asdf': 'table'},传递一个字典，标示表格的属性值。\n",
    "\n",
    "- parse_dates : bool, optional,解析日期\n",
    "\n",
    "- tupleize_cols : bool, optional,不推荐使用\n",
    "\n",
    "- thousands : str, optional,千位分隔符\n",
    "\n",
    "- encoding : str or None, optional,解码方式，默认使用文档提供的编码\n",
    "\n",
    "- decimal : str, default ‘.’,小数点标示，默认使用“.”\n",
    "- converters : dict, default None,转换某些列的函数的字典：键为列名或者整数，值为转换函数，函数只能传入一个参数，就是该列单元格的值。\n",
    "\n",
    "- na_values : iterable, default None,标示那些为NA值\n",
    "- keep_default_na : bool, default True,保持默认的NA值，与na_values一起使用"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### read_sql\n",
    "\n",
    "> read_sql(sql, con, index_col=None, coerce_float=True, params=None, parse_dates=None, columns=None, chunksize=None)\n",
    "\n",
    "效果：将SQL查询或数据库表读入DataFrame。\n",
    "\n",
    "此功能是一个方便的包装和 （为了向后兼容）。它将根据提供的输入委派给特定的功能。SQL查询将被路由到，而数据库表名将被路由到。请注意，委派的功能可能有更多关于其功能的特定说明，此处未列出。\n",
    "\n",
    "**参数详解:**\n",
    "\n",
    "- sql : 要执行的SQL查询或表名。\n",
    "\n",
    "- con : 使用SQLAlchemy可以使用该库支持的任何数据库。如果是DBAPI2对象，则仅支持sqlite3。\n",
    "\n",
    "- index_col : string or list of strings, optional, default: Nonem,要设置为索引的列（MultiIndex）。\n",
    "\n",
    "- coerce_float : boolean, default True,,尝试将非字符串，非数字对象（如decimal.Decimal）的值转换为浮点，这对SQL结果集很有用。\n",
    "\n",
    "- parse_dates : list or dict, default: None,要解析为日期的列名列表。在解析字符串时，格式字符串是strftime兼容的格式字符串，或者是（D、s、ns、ms、us），以防解析整型时间戳。\n",
    "- columns : list, default: None,从SQL表中选择的列名列表（仅在读取表时使用）。\n",
    "\n",
    "- chunksize : int, default None,如果指定，则返回一个迭代器，其中chunksize是要包含在每个块中的行数。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**使用案例**\n",
    "```python\n",
    "import pandas as pd\n",
    "from sqlalchemy import create_engine\n",
    "\n",
    "def pandas_db_helper(db):\n",
    "    \"\"\"\n",
    "    db\n",
    "    'postgresql://postgres:0000@127.0.0.1:5432/xiaomuchong'\n",
    "    \"mysql+pymysql://root:0000@127.0.0.1:3306/srld?charset=utf8mb4\"\n",
    "    \"sqlite: ///sqlite3.db\"\n",
    "    \"\"\"\n",
    "    engine = create_engine(db)\n",
    "    conn = engine.connect()\n",
    "    return conn\n",
    "\n",
    "db_conn = pandas_db_helper(\"sqlite: ///sqlite3.db\")\n",
    "\n",
    "data = pd.read_sql(sql=\"topics\", con=db_conn, columns=[\"topic_url\", \"reply_num\"])\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### read_sql_table\n",
    "\n",
    "> read_sql_table(table_name, con, schema=None, index_col=None, coerce_float=True, parse_dates=None, columns=None, chunksize=None)\n",
    "\n",
    "效果：将SQL数据库表读入DataFrame。\n",
    "\n",
    "给定一个表名和一个SQLAlchemy可连接，返回一个DataFrame。此功能不支持DBAPI连接。\n",
    "参数详解\n",
    "\n",
    "- table_name : string,数据库中SQL表的名称。\n",
    "- con : SQLAlchemy connectable (or database string URI),不支持SQLite DBAPI连接模式。\n",
    "- schema : string, default None,要查询的数据库中的SQL模式的名称（如果数据库flavor支持此功能）。如果为None（默认值），则使用默认架构。\n",
    "- index_col : string or list of strings, optional, default: None,要设置为索引的列（MultiIndex）。\n",
    "- coerce_float : boolean, default True,尝试将非字符串，非数字对象（如decimal.Decimal）的值转换为浮点值。可能导致精度损失。\n",
    "- parse_dates : list or dict, default: None,要解析为日期的列名列表。{column_name：format string}的字典，其中格式字符串在解析字符串时间时与strftime兼容，或者在解析整数时间戳的情况下是（D，s，ns，ms，us）之一。{column_name：arg dict}的字典，其中arg dict对应于pandas.to_datetime（）的关键字参数。对于没有本机Datetime支持的数据库（如SQLite）特别有用。\n",
    "- columns : list, default: None,从SQL表中选择的列名列表\n",
    "- chunksize : int, default None,如果指定，则返回一个迭代器，其中chunksize是要包含在每个块中的行数。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**使用案例**\n",
    "```python\n",
    "import pandas as pd\n",
    "import pymysql\n",
    "from sqlalchemy import create_engine\n",
    "  \n",
    "con = create_engine('mysql+pymysql://user_name:password@127.0.0.1:3306/database_name')\n",
    "data = pd.read_sql_table(\"table_name\", con)\n",
    "data.to_csv(\"table_name.csv\")\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 第2部分：文件输出"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### to_csv\n",
    "\n",
    "> DataFrame.to_csv(path_or_buf=None, sep=', ', na_rep='', float_format=None, columns=None, header=True, index=True, index_label=None, mode='w', encoding=None, compression='infer', quoting=None, quotechar='\"', line_terminator=None, chunksize=None, tupleize_cols=None, date_format=None, doublequote=True, escapechar=None, decimal='.')\n",
    "\n",
    "**参数详解**\n",
    "\n",
    "- path_or_buf=None： 字符串或文件句柄，默认无文件路径或对象，如果没有提供，结果将返回为字符串。\n",
    "- sep : 默认字符 ‘ ，’输出文件的字段分隔符。\n",
    "- na_rep : 字符串，默认为'',浮点数格式字符串\n",
    "- float_format : 字符串，默认为 None,浮点数格式字符串\n",
    "- columns : 顺序，可选列写入\n",
    "- header : 字符串或布尔列表，默认为true写出列名。如果给定字符串列表，则假定为列名的别名。\n",
    "- index : 布尔值，默认为Ture,写入行名称（索引）\n",
    "- index_label :字符串或序列，或False,默认为None如果需要，可以使用索引列的列标签。如果没有给出，且标题和索引为True，则使用索引名称。如果数据文件使用多索引，则应该使用这个序列。如果值为False，不打印索引字段。在R中使用index_label=False 更容易导入索引.\n",
    "- mode : 值为‘str’，字符串Python写模式，默认“w”\n",
    "- encoding : 字符串，可选,表示在输出文件中使用的编码的字符串，Python 2上默认为“ASCII”和Python 3上默认为“UTF-8”。\n",
    "- compression : 字符串，可选项，表示在输出文件中使用的压缩的字符串，允许值为“gzip”、“bz2”、“xz”，仅在第一个参数是文件名时使用。\n",
    "- line_terminator : 字符串，默认为 ‘\\n’，在输出文件中使用的换行字符或字符序列\n",
    "- quoting : optional CSV模块的可选常量，默认值为to_csv.QUOTE_MINIMAL。如果设置了浮点格式，那么浮点将转换为字符串，因此csv.QUOTE_NONNUMERIC会将它们视为非数值的。\n",
    "- quotechar : 字符串（长度1），默认“”用于引用字段的字符\n",
    "- doublequote : 布尔，默认为Ture，控制一个字段内的quotechar\n",
    "- escapechar :字符串（长度为1），默认为None在适当的时候用来转义sep和quotechar的字符\n",
    "- chunksize : 一次写入行\n",
    "- date_format :字符串，默认为None.字符串对象转换为日期时间对象\n",
    "- decimal: 字符串，默认’。’字符识别为小数点分隔符。例如。欧洲数据使用 ​​’"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### to_excel\n",
    "> to_excel(self, excel_writer, sheet_name='Sheet1', na_rep='', float_format=None,columns=None,\n",
    "header=True, index=True, index_label=None,startrow=0, startcol=0, engine=None,\n",
    "merge_cells=True, encoding=None,inf_rep='inf', verbose=True, freeze_panes=None)\n",
    "\n",
    "**常用参数解析**\n",
    "- excel_writer ： ExcelWriter目标路径\n",
    "- sheet_name ：excel表名命名\n",
    "- na_rep ： 缺失值填充 ，可以设置为字符串\n",
    "- columns ：选择输出的的列存入\n",
    "- header :指定作为列名的行，默认0，即取第一行，数据为列名行以下的数据；若数据不含列名，则设定 header = None；\n",
    "- index：默认为True，显示index，当index=False 则不显示行索引（名字）\n",
    "- index_label：设置索引列的列名"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "多张表保存到一个excel\n",
    "```python\n",
    "with pd.ExcelWriter(path=\"结果.xlsx\") as writer:\n",
    "    exam_data.to_excel(excel_writer=writer, sheet_name='试题数据', index=False)\n",
    "    student_total_score.to_excel(excel_writer=writer, sheet_name='学生总成绩', index=False)\n",
    "    student_semester_total.to_excel(excel_writer=writer, sheet_name='每个学生各学期总成绩', index=False)\n",
    "    course_avg_score.to_excel(excel_writer=writer, sheet_name='各门课程平均成绩', index=False)\n",
    "    greater_than_avg_student.to_excel(excel_writer=writer, sheet_name='各学期大于本课程平均成绩的学生姓名及成绩', index=False)\n",
    "    writer.save()\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "固定输出列的顺序\n",
    "```python\n",
    "data = pd.DataFrame(data=data_list)\n",
    "# 固定列表的输出顺序\n",
    "data = data.loc[:, columns]\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### to_sql"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>name</th>\n",
       "      <th>age</th>\n",
       "      <th>city</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>张三</td>\n",
       "      <td>18</td>\n",
       "      <td>北京</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>李四</td>\n",
       "      <td>19</td>\n",
       "      <td>上海</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>王五</td>\n",
       "      <td>20</td>\n",
       "      <td>广州</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>赵六</td>\n",
       "      <td>21</td>\n",
       "      <td>深圳</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>孙七</td>\n",
       "      <td>22</td>\n",
       "      <td>武汉</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  name  age city\n",
       "0   张三   18   北京\n",
       "1   李四   19   上海\n",
       "2   王五   20   广州\n",
       "3   赵六   21   深圳\n",
       "4   孙七   22   武汉"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import pandas as pd\n",
    "data = [\n",
    "       {\"name\":\"张三\",\"age\":18,\"city\":\"北京\"},\n",
    "       {\"name\":\"李四\",\"age\":19,\"city\":\"上海\"},\n",
    "       {\"name\":\"王五\",\"age\":20,\"city\":\"广州\"},\n",
    "       {\"name\":\"赵六\",\"age\":21,\"city\":\"深圳\"},\n",
    "       {\"name\":\"孙七\",\"age\":22,\"city\":\"武汉\"}\n",
    "]\n",
    "df = pd.DataFrame(data,columns=[\"name\",\"age\",\"city\"])\n",
    "df"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```python\n",
    "from sqlalchemy import create_engine\n",
    " \n",
    "table_name = \"user\"\n",
    " \n",
    "engine = create_engine(\n",
    "    \"mysql+pymysql://root:0000@127.0.0.1:3306/db_test?charset=utf8\",\n",
    "    max_overflow=0,  # 超过连接池大小外最多创建的连接\n",
    "    pool_size=5,  # 连接池大小\n",
    "    pool_timeout=30,  # 池中没有线程最多等待的时间，否则报错\n",
    "    pool_recycle=-1  # 多久之后对线程池中的线程进行一次连接的回收（重置）\n",
    ")\n",
    "conn = engine.connect()\n",
    "df.to_sql(table_name, conn, if_exists='append',index=False)\n",
    "```\n",
    "上面代码已经实现将我们构造的df数据保存MySQL，现在提一些注意点\n",
    "注意事项：  \n",
    "1、我们用的库是sqlalchemy，官方文档提到to_sql是被sqlalchemy支持  \n",
    "文档地址：\n",
    "http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.to_sql.html  \n",
    "2、数据库配置用你自己的数据库配置，db_flag为数据库类型，根据不同情况更改，在保存数据之前，要先创建数据库字段。  \n",
    "3. engine_config为数据库连接配置信息  \n",
    "4、create_engine是根据数据库配置信息创建连接对象  \n",
    "5、if_exists = 'append',追加数据  \n",
    "6、index = False 保存时候，不保存df的行索引，这样刚好df的3个列和数据库的3个字段一一对应，正常保存，如果不设置为false的话，数据相当于4列，跟MySQL 3列对不上号，会报错"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.5"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": false,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": true
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
